#include "stdTcpService.h"
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cstring>
#include <arpa/inet.h>
#include <stdio.h>
#include <cctype>

using namespace std;

#include <stdlib.h>
#include <pthread.h>
#include <json-c/json.h>

// 设置监听
void StdTcpServer::setListen(int port)
{

    // 创建通信文件描述符
    int socketfd = socket(AF_INET, SOCK_STREAM, 0);
    if (socketfd == -1)
    {
        perror("socket create error");
        _exit(-1);
    }

    // 设置地址复用
    // bind error
    int optVal = 1;
    int ret = setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR, &optVal, sizeof(optVal));
    if (ret == -1)
    {
        perror("setsockopt error");
        _exit(-1);
    }
    // 绑定服务器的ip和端口信息
    // sockaddr localAdderss;//写数据时不好用
    sockaddr_in localAdderss;
    // 清除脏数据
    memset(&localAdderss, 0, sizeof(localAdderss));
    // 地址族
    localAdderss.sin_family = AF_INET;         // IPV4
    localAdderss.sin_port = htons(port);       // 转字节序
    localAdderss.sin_addr.s_addr = INADDR_ANY; // IP地址
    ret = bind(socketfd, (const sockaddr *)&localAdderss, sizeof(localAdderss));
    if (ret == -1)
    {
        perror("bind error");
        _exit(-1);
    }
    // 监听
    ret = listen(socketfd, 10);
    if (ret == -1)
    {
        perror("listen error");
        _exit(-1);
    }
    // 维护一下端口属性
    m_port = port;
    // 维护一下socket句柄属性
    m_sockfd = socketfd;
}

// 得到与客户端的通信句柄(类)
StdTcpSocket *StdTcpServer::getClientSocket()
{
    int connfd = accept(m_sockfd, NULL, NULL); // 二 三 参数用于接收客户端信息NULL表示不关心
    if (connfd == -1)
    {
        perror("accept error");
        _exit(-1);
    }
    cout << "有新的客户端连接,connfd:" << connfd << endl;

    // 通信类
    //替换为智能指针
    //to do...
    StdTcpSocket *clientSock = new StdTcpSocket;
    clientSock->setAttrConnfd(connfd);
    return clientSock;
}

// 连接服务器
bool StdTcpSocket::connectToServer(const char *ip, int port)
{
    // 创建通信文件描述符
    int socketfd = socket(AF_INET, SOCK_STREAM, 0);
    if (socketfd == -1)
    {
        perror("socket create error");
        return false;
    }

    // 连接服务器
    // 绑定服务器的ip和端口信息
    // sockaddr localAdderss;//写数据时不好用
    sockaddr_in serverAdderss;
    // 清除脏数据
    memset(&serverAdderss, 0, sizeof(serverAdderss));
    // 地址族
    serverAdderss.sin_family = AF_INET;   // IPV4
    serverAdderss.sin_port = htons(port); // 转字节序

    // 服务器IP
    const char *serverip = ip;
    inet_pton(AF_INET, serverip, &serverAdderss.sin_addr.s_addr);

    int ret = connect(socketfd, (const sockaddr *)&serverAdderss, sizeof(serverAdderss));
    if (ret == -1)
    {
        perror("connect error");
        return false;
    }
    // 维护套接字句柄
    m_connfd = socketfd;
    return true;
}

// 发送数据
int StdTcpSocket::sendMessage(const void *sendMsg, size_t size)
{
    // 发送数据大小
    write(m_connfd, &size, sizeof(size_t));
    // 发送数据本身
    int writeBytes = write(m_connfd, sendMsg, size);
    return writeBytes;
}

// 发送数据
int StdTcpSocket::sendMessage(const std::string &sendMsg)
{
    return sendMessage(sendMsg.c_str(), sendMsg.size());
}

// 接收数据
int StdTcpSocket::recvMessage(void *buf, size_t size)
{
    return 0;
}

// 接收数据
int StdTcpSocket::recvMessage(std::string &recvMessage)
{
    // 1、先得到数据包的大小
    size_t dataSize = 0;
    int readBytes = read(m_connfd, &dataSize, sizeof(size_t));
    if (readBytes < 0)
    {
        perror("read error:");
        return readBytes;
    }
    // 2、再获得数据本身
    char *msg = new char[dataSize + 1];
    if (msg == nullptr)
    {
        // todo
    }
    // 清除脏数据
    memset(msg, 0, sizeof(char) * (dataSize + 1));
    size_t totalRecvived = 0;
    while (totalRecvived < dataSize)
    {
        // 当因为意外导致读取字节数不足时,还要读dataSize - totalRecvived
        // 指针已经挪动了totalRecvived，为避免覆盖msg + totalRecvived
        readBytes = read(m_connfd, msg + totalRecvived, dataSize - totalRecvived);
        if (readBytes < 0)
        {
            perror("read error:");
            delete[] msg;
           return readBytes;
        }else if(readBytes==0)
        {
           
            delete[] msg;
            return readBytes;
            
        }
        totalRecvived += readBytes;
    }
    // 赋值
    recvMessage = msg;
    // 释放堆空间
    delete[] msg;

    return dataSize;
}

// 设置通信句柄
void StdTcpSocket::setAttrConnfd(int connfd)
{
    this->m_connfd = connfd;
}
